﻿package com.dcliment.utils
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Loader;
	import flash.display.SimpleButton;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.system.ApplicationDomain;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	import flash.utils.getQualifiedSuperclassName;
	
	
	/**
		Provides utility functions for DisplayObjects/DisplayObjectContainers.
		
	*/
	public class DisplayObjectUtil 
	{
		
		/**
			Returns the children of a <code>DisplayObjectContainer</code> as an <code>Array</code>.
			
			@param parent: The <code>DisplayObjectContainer</code> from which to get the children from.
			@return All the children of the <code>DisplayObjectContainer</code>.
		*/
		public static function getChildren(parent:DisplayObjectContainer):Array 
		{
			const children:Array = new Array();
			var i:int            = -1;
			
			while (++i < parent.numChildren)
				children.push(parent.getChildAt(i));
			
			return children;
		}
		
		public static function removeChildrenOf($target:DisplayObjectContainer):void
		{
			var target:DisplayObjectContainer = $target;
			
			while(target.numChildren != 0)
				target.removeChildAt(0);
		}
		/**
			Returns the X and Y offset to the top left corner of the <code>DisplayObject</code>. The offset can be used to position <code>DisplayObject</code>s whose alignment point is not at 0, 0 and/or is scaled.
			
			@param displayObject: The <code>DisplayObject</code> to align.
			@return The X and Y offset to the top left corner of the <code>DisplayObject</code>.
			@example
				<code>
					var box:CasaSprite = new CasaSprite();
					box.scaleX         = -2;
					box.scaleY         = 1.5;
					box.graphics.beginFill(0xFF00FF);
					box.graphics.drawRect(-20, 100, 50, 50);
					box.graphics.endFill();
					
					const offset:Point = DisplayObjectUtil.getOffsetPosition(box);
					
					trace(offset)
					
					box.x = 10 + offset.x;
					box.y = 10 + offset.y;
					
					this.addChild(box);
				</code>
		*/
		public static function getOffsetPosition(displayObject:DisplayObject):Point {
			const bounds:Rectangle = displayObject.getBounds(displayObject);
			const offset:Point     = new Point();
			
			offset.x = (displayObject.scaleX > 0) ? bounds.left * displayObject.scaleX * -1 : bounds.right * displayObject.scaleX * -1;
			offset.y = (displayObject.scaleY > 0) ? bounds.top * displayObject.scaleY * -1 : bounds.bottom * displayObject.scaleY * -1;
			
			return offset;
		}
		
		/**
			Returns the first display object with the specified name that exists in the display tree of the provided <code>DisplayObjectContainer</code>.
			
			@param parent: The <code>DisplayObjectContainer</code> in which to get the child from.
			@param name: The name of the child to return.
			@return The first child display object with the specified name, or <code>null</code> if no display object was found.
		*/
		public static function getChildByNameRecursive(parent:DisplayObjectContainer, name:String):DisplayObject {
			var child:DisplayObject = parent.getChildByName(name);
			
			if (child != null)
				return child;
			
			var i:int = -1;
			
			while (++i < parent.numChildren) {
				child = parent.getChildAt(i);
				
				if (child is DisplayObjectContainer) {
					child = DisplayObjectUtil.getChildByNameRecursive(child as DisplayObjectContainer, name);
					
					if (child != null)
						return child;
				}
			}
			
			return null;
		}
		
		
		/**
		* ADDED BY DENNIS
		*/
		
		/**
		 * Traces out the children of the provided MovieClip
		 * 
		 * @param mc - MovieCilp to run trace one
		 * 
		 */		
		public static function traceChildren(dispObj:*):void
		{
			for (var i:uint = 0; i < dispObj.numChildren; i++){
				trace ('\t|\t ' +i+'.\t name:' + dispObj.getChildAt(i).name + '\t type:' + typeof (dispObj.getChildAt(i))+ '\t' + dispObj.getChildAt(i));
			}
		}
		
		/**
		 * Gets library object from fla library
		 *
		 */
		public static function getLibraryObject($className:String, $appDomain:ApplicationDomain = null, ...arguments):*
		{
			var ClassReference:Class;
			
			if($appDomain) // untested but the theory is sound
				ClassReference = Class($appDomain.getDefinition($className));
			else
				ClassReference = Class(ApplicationDomain.currentDomain.getDefinition($className));
							
			if (arguments.length > 10)
				throw new Error('You have passed more arguments than the "construct" method accepts (accepts ten or less).');
			
			switch (arguments.length) {
				case 0 :
					return new ClassReference();
				case 1 :
					return new ClassReference(arguments[0]);
				case 2 :
					return new ClassReference(arguments[0], arguments[1]);
				case 3 :
					return new ClassReference(arguments[0], arguments[1], arguments[2]);
				case 4 :
					return new ClassReference(arguments[0], arguments[1], arguments[2], arguments[3]);
				case 5 :
					return new ClassReference(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
				case 6 :
					return new ClassReference(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
				case 7 :
					return new ClassReference(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]);
				case 8 :
					return new ClassReference(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]);
				case 9 :
					return new ClassReference(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8]);
				case 10 :
					return new ClassReference(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]);
			}
		}
		
		/**
		 * Get library object from loaded swf using SwfLoad class
		 *  
		 * @param $swfLibrary
		 * @param $className
		 * @return 
		 * 
			
		public static function getSwfloadObject($swfLibrary:SwfLoad, $className:String):*
		{
			var ClassReference:Class = $swfLibrary.getClassByName($className);
			
			var mc:* = new ClassReference();
			
			return mc;
		}
		*/	 
		public static function duplicateDispalyObject(target:DisplayObject):DisplayObject
		{
			var targetClass:Class = Object(target).constructor;
			var duplicate:DisplayObject = new targetClass();
				duplicate.transform = target.transform;
				duplicate.filters = target.filters;
				duplicate.cacheAsBitmap = target.cacheAsBitmap;
				duplicate.opaqueBackground = target.opaqueBackground;
			
			return duplicate
		}
		
		
		public static function create(className:String):Object{
			var clazz:Class= Class(ApplicationDomain.currentDomain.getDefinition(className));
			return new clazz();
		}
		/**
		 * Checks what the super class of an obj is
		 * 
		 */
		public static function getSuperClass(obj:*):Class
		{
			var className:String = getQualifiedClassName( obj );
			var superClassName:String = getQualifiedSuperclassName(obj);
			var superClass:Class = getDefinitionByName(superClassName) as Class;			
			return superClass; 
		}
		
		//-------------------------
		// Set DisplayObject Position
		
		//sets the Display Object of the top of the stack
		public static function sendFront($do:DisplayObject):void 
		{
			$do.parent.setChildIndex($do,$do.parent.numChildren - 1);
		}
		
		//sends @_do below @child
		public static function sendBelow($do:DisplayObject, $child:DisplayObject):void 
		{
			$do.parent.setChildIndex($do, $do.parent.getChildIndex($child))
		}
		
		//sets @_do above @child
		public static function sendAbove($do:DisplayObject, $child:DisplayObject):void 
		{   
			$do.parent.setChildIndex($do, $do.parent.getChildIndex($child));
			$do.parent.swapChildren($do, $child);
		}
		
		//sets @_do at the back of the display list stack
		public static function sendBack($do:DisplayObject):void 
		{               
			$do.parent.setChildIndex($do,0);
		}
		
	}
}